//
// Created by chnlich on 6/27/15.
//

#ifndef STORAGE_ORIENTED_PARALLEL_ADVANCED_DATA_STRUCTURE_DATABASE_TYPE_H
#define STORAGE_ORIENTED_PARALLEL_ADVANCED_DATA_STRUCTURE_DATABASE_TYPE_H

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <pthread.h>
#include <assert.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h>

#define DB_BUFFER_BITS 24
#define DB_BUFFER (1<<DB_BUFFER_BITS)

struct database_item {
	char *key;
	void *value;
};

struct database_item *new_database_item(const char *key, const void *value, int32_t max_key_len, int32_t max_value_len);

int32_t set_database_item(struct database_item *dbi, const char *key, const void *value, int32_t max_key_len,
                          int32_t max_value_len);

void delete_database_item(struct database_item *);

typedef int32_t(*cond_func)(struct database_item *);

struct database_item_list {
	struct database_item dbi;
	struct database_item_list *next;
};

void delete_database_item_list(struct database_item_list *);

struct database_keypair {
	char *l;
	char *r;
};

struct database_node {
	struct database_node *c[2];
	struct database_item *v;
};

struct database_node *new_database_node();

void delete_database_node(struct database_node *);

struct database {
	struct database_node *root;
	pthread_t tid;
	pthread_rwlock_t trie_lock;
	pthread_rwlock_t buffer_lock;
	int32_t thread_signal;
	int32_t l, r;
	int32_t key_length, value_length;
	struct database_item *buffer[DB_BUFFER];
};

#define FULL_BUFFER(l, r) (((r+1)&(DB_BUFFER-1)) == l)

int32_t database_init(struct database *db, int32_t kl, int32_t vl);

int32_t database_close(struct database *db);

// clone dbi and insert
int32_t database_insert(struct database *db, struct database_item *dbi);

int32_t database_delete(struct database *db, cond_func func);

int32_t database_delete_from_key(struct database *db, struct database_keypair *dbk);

int32_t database_search(struct database *db, cond_func func, struct database_item_list **dbil);

int32_t database_search_from_key(struct database *db, struct database_keypair *dbk, struct database_item_list **dbil);

int32_t database_save(struct database *db, const char *file_name);

int32_t database_load(struct database *db, const char *file_name);

#endif //STORAGE_ORIENTED_PARALLEL_ADVANCED_DATA_STRUCTURE_DATABASE_TYPE_H
